package swym.client.old;

import java.io.*;
import java.util.*;
import java.util.Scanner;
import java.lang.management.*;
import java.util.zip.*;
import swym.server.file.FileChunk;

import swym.server.file.FileChunk;

public class ChecksumStore
{
    private ChecksumStoreListener listener;
	private int chunkSize = 512;
	private File checksumStore;
	private File watchDir;	

	public ChecksumStore(File watchDir, ChecksumStoreListener listener)
	{
		this.watchDir = watchDir;
		checksumStore = new File(watchDir.getAbsolutePath() + "/checksumStore");
		try{checksumStore.createNewFile();}catch(Exception e){}
        this.listener = listener;
	}

	public File getChecksumStore()
	{
		return checksumStore;
	}

	public boolean checkInStore(File file)
	{
		boolean output = false;
		try
		{
		BufferedReader read = new BufferedReader(new FileReader(checksumStore));
		String fileName = file.getAbsolutePath().replace(watchDir.getAbsolutePath(),"");
		Scanner scan;
		String line;

		while((line = read.readLine()) != null && !output)
		{
			scan = new Scanner(line);
			scan.useDelimiter(":");

			if(scan.hasNext() && scan.next().equals(fileName))
				output = true;
		}
		read.close();
		}
		catch(Exception e){e.printStackTrace();}
		
		return output;		
	}

	public void storeChecksum(File file, ArrayList<Long> chksum)
	{
		try
		{
		String fileName = file.getAbsolutePath().replace(watchDir.getAbsolutePath(),"");
		BufferedWriter out = new BufferedWriter(new FileWriter(checksumStore, true));
		out.write(fileName + ":");
		for(long cs :  chksum)
			out.write(cs + ":");
		out.write("\n");
		out.close();
		}
		catch(Exception e){e.printStackTrace();} 
	}

	public ArrayList<Long> getChecksum(File file)
	{
		ArrayList<Long> output  = new ArrayList<Long>();

		try
		{
		BufferedReader read = new BufferedReader(new FileReader(checksumStore));
		Scanner scan;
		boolean finished = false;
		String fileName = file.getAbsolutePath().replace(watchDir.getAbsolutePath(),"");
		String line;

		while((line = read.readLine()) != null && !finished)
		{
			scan = new Scanner(line).useDelimiter(":");

			if(scan.hasNext() && scan.next().equals(fileName))
			{
				while(scan.hasNext())
					output.add(Long.parseLong(scan.next()));
				finished = true;
			}
		}
		read.close();
		}
		catch(Exception e){e.printStackTrace();}
		return output;	
	}

	public ArrayList<Long> performChecksum(File file)
	{
		ArrayList<Long> output = new ArrayList<Long>();
		Checksum chkSum = new Adler32();	

		try
		{
			int numRead;		
			InputStream fis =  new FileInputStream(file);
			byte[] tempBuf = new byte[chunkSize];
			
			do
			{
				numRead = fis.read(tempBuf);
				if (numRead >= 0)
  				{
					chkSum.update(tempBuf, 0, numRead);
					output.add(chkSum.getValue());
					chkSum.reset();
				}
			}
			while (numRead != -1);
  
			fis.close();  			
		}
		catch(FileNotFoundException fnfe)
		{
			fnfe.printStackTrace();
		}
		catch(IOException ioe)
		{
			ioe.printStackTrace();
		}
		
		return output;	
	}

	public void performComparison(File file)
	{
        ArrayList<Long> oldChk = getChecksum(file);
		Checksum chkSum = new Adler32();	

		try
		{
			int numRead;
            int offset = 0;
			InputStream fis =  new FileInputStream(file);
			byte[] tempBuf = new byte[chunkSize];
			
			do
			{
                numRead = fis.read(tempBuf);	
                if (numRead >= 0)
  				{
					chkSum.update(tempBuf, 0, numRead);
                    if(oldChk.get(offset) != chkSum.getValue())
                        listener.differenceFound(file,new FileChunk(offset ));					

					chkSum.reset();
				}

                offset++;
			}
			while (numRead != -1);
  
			fis.close();  
            listener.finishedComparison(file);			
		}
		catch(FileNotFoundException fnfe)
		{
			fnfe.printStackTrace();
            listener.comparisonError(file);
		}
		catch(IOException ioe)
		{
			ioe.printStackTrace();
            listener.comparisonError(file);
		}	
	}
}
